<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Shop\Plugin;

use Admin\Data\Common;
use Admin\Data\Config;
use Admin\Entity\Delivery;
use Admin\Entity\Region;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator;
use Imagine\Gd\Imagine;
use Imagine\Image\Box;
use Imagine\Image\Palette\RGB;
use Imagine\Image\Point;
use Laminas\Config\Factory;
use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
use Laminas\Mvc\I18n\Translator;
use Laminas\Session\Container;
use PHPQRCode\QRcode;
use User\Entity\User;

class ShopPlugin extends AbstractPlugin
{
    private $entityManager;
    private $translator;
    private $sessionUser;
    private $dbshopSession;

    public function __construct(
        EntityManager   $entityManager,
        Translator      $translator
    )
    {
        $this->entityManager    = $entityManager;
        $this->translator       = $translator;

        if($this->sessionUser == null) $this->sessionUser = new Container('dbshopUser');
        if($this->dbshopSession == null) $this->dbshopSession = new Container('dbshopSession');
    }

    /**
     * 检测会员是否登录，如果不存在则清除session
     * @return false|object|User
     */
    public function checkUserLoginStatus()
    {
        return $this->sessionUser->offsetExists('user_id');
    }

    /**
     * 设置会员登录信息
     * @param $key
     * @param $value
     */
    public function setUserLoginData($key, $value)
    {
        if($this->sessionUser->offsetGet($key)) $this->sessionUser->offsetSet($key, $value);
    }

    /**
     * 获取会员登录信息
     * @param string $key 空为返回登录的全部信息
     * @return array|mixed|null
     */
    public function getUserLoginData($key = '')
    {
        return !empty($key) ? $this->sessionUser->offsetGet($key) : $this->sessionUser->getArrayCopy();
    }

    /**
     * 设置shop通用的 session 信息
     * @param $key
     * @param $value
     */
    public function setDbshopSessionData($key, $value)
    {
        $this->dbshopSession->offsetSet($key, $value);
    }

    /**
     * 获取shop通用的 session 信息
     * @param $key
     * @return mixed|string|null
     */
    public function getDbshopSessionData($key)
    {
        return $this->dbshopSession->offsetExists($key) ? $this->dbshopSession->offsetGet($key) : '';
    }

    /**
     * 注销shop通用的 session 信息
     * @param $key
     */
    public function unsetDbshopSessionData($key)
    {
        if ($this->dbshopSession->offsetExists($key)) $this->dbshopSession->offsetUnset($key);
    }

    /**
     * 注销验证码相关的session信息
     */
    public function unsetPhoneCaptchaData()
    {
        if ($this->dbshopSession->offsetExists('phoneCaptcha')) $this->dbshopSession->offsetUnset('phoneCaptcha');
        if ($this->dbshopSession->offsetExists('phoneNumber'))  $this->dbshopSession->offsetUnset('phoneNumber');
        if ($this->dbshopSession->offsetExists('expiredTime'))  $this->dbshopSession->offsetUnset('expiredTime');
    }

    /**
     * 获取动态绑定的物流id
     * @return array
     */
    public function getExpressCodeIdArray()
    {
        $deliveryList       = $this->entityManager->getRepository(Delivery::class)->findBy(['deliveryState' => 1]);
        $expressCodeArray   = [];
        if ($deliveryList) foreach ($deliveryList as $value) {
            if (!empty($value->getDeliveryNameCode())) $expressCodeArray[$value->getDeliveryId()] = $value->getDeliveryNameCode();
        }

        return $expressCodeArray;
    }

    /**
     * 获取货币信息
     * @return array|\Laminas\Config\Config|mixed
     */
    public function getShopCurrency()
    {
        $currencyArray = Common::readConfigFile('currency');
        if($this->dbshopSession->offsetGet('currencyCode')) {
            $currencyArray['default'] = Common::configValue($this->dbshopSession->offsetGet('currencyCode'), 'currency');
        }

        return $currencyArray;
    }

    /**
     * 获取默认货币信息
     * @return mixed|string[]|null
     */
    public function getShopDefaultCurrency()
    {
        $defaultCurrency = Common::configValue('default', 'currency');
        if($this->dbshopSession->offsetGet('currencyCode') && $this->dbshopSession->offsetGet('currencyCode') != $defaultCurrency['code']) $defaultCurrency = Common::configValue($this->dbshopSession->offsetGet('currencyCode'), 'currency');

        return $defaultCurrency;
    }

    /**
     * @param $price
     * @return string
     */
    public function shopCurrency($price)
    {
        $defaultCurrency = $this->getShopDefaultCurrency();
        return $defaultCurrency['symbol'] . number_format($price * $defaultCurrency['rate'], 2, '.', '');
    }

    /**
     * 获取退货商品原因
     * @param string $title
     * @return array|string[]
     */
    public function getReturnGoodsReason($title = '')
    {
        $array  = ['' => !empty($title) ? $title : $this->translator->translate('选择退款原因')];
        $reason = explode("\r\n", Common::configValue('order', 'config')['order_return_cause']);
        if (!empty($reason)) foreach ($reason as $value) {
            $array[$value] = $value;
        }
        return $array;
    }

    /**
     * 订单状态编码
     * @param $statusStr
     * @return mixed
     */
    public function getOrderStatusCode($statusStr)
    {
        return Common::orderStatusCode($statusStr);
    }

    /**
     * 获取启用的第三方登录
     * @return array
     */
    public function enableOtherLogin()
    {
        $enableLoginArray = Common::configValue('enableLogin', 'customer');
        if (empty($enableLoginArray)) return [];

        $isMobile = Common::isMobile();
        $isWechat = Common::isWeixin();
        $loginArray = [];
        foreach ($enableLoginArray as $loginValue) {
            if ($isMobile) {
                if ($isWechat && !in_array($loginValue, ['wechat'])) continue;
                if (!$isWechat && in_array($loginValue, ['wechatScan', 'alipay', 'wechat'])) continue;
            } else {
                if (in_array($loginValue, ['wechat'])) continue;
            }
            $loginArray[] = $loginValue;
        }

        return $loginArray;
    }

    /**
     * 返回上一页
     * @return mixed
     */
    public function toReferer()
    {
        $referer = $this->getController()->params()->fromHeader('Referer');
        if($referer) {
            $refererUrl     = $referer->uri()->getPath().(!empty($referer->uri()->getQuery()) ? '?'.$referer->uri()->getQuery() : '').(!empty($referer->uri()->getFragment()) ? '#'.$referer->uri()->getFragment() : '');
            $refererHost    = $referer->uri()->getHost();
            $host           = $this->getController()->getRequest()->getUri()->getHost();
            if ($refererUrl && $refererHost == $host) {
                return $this->getController()->redirect()->toUrl($refererUrl);
            }
        }
        return $this->getController()->redirect()->toRoute('shop');
    }

    /**
     * 验证get的CSRF Token
     * @return bool
     */
    public function validatorQueryCsrf()
    {
        $csrfValue = $this->getController()->getRequest()->getQuery('qToken');
        if(empty($csrfValue) || ($csrfValue && $csrfValue != $this->dbshopSession->offsetGet('shopQueryToken'))) {
            $this->getController()->flashMessenger()->addErrorMessage($this->translator->translate('不正确的请求!'));
            return false;
        }
        $this->dbshopSession->offsetSet('shopQueryToken', '');

        return true;
    }

    /**
     * 前台公共分页方法
     * @param Query $query
     * @param int $pageNumber       页码
     * @param int $itemCountPerPage 每页显示的数量
     * @param bool $fetchJoinCollection
     * @return \Laminas\Paginator\Paginator
     */
    public function shopPaginator(Query $query, $pageNumber = 1, $itemCountPerPage = 16, $fetchJoinCollection = false)
    {
        $adapter    = new DoctrinePaginator(new Paginator($query, $fetchJoinCollection));
        $paginator  = new \Laminas\Paginator\Paginator($adapter);
        $paginator->setItemCountPerPage($itemCountPerPage);
        $paginator->setCurrentPageNumber($pageNumber);

        if (Common::isMobile()) $paginator->setPageRange(4);

        return $paginator;
    }

    /**
     * 前台对应列表的每页显示商品数
     * @param $key
     * @return int|mixed
     */
    public function shopPerPageNum($key)
    {
        $templateConfig = Factory::fromFile('module/Shop/view/'.Common::getShopDefaultTemplate().'/shop/template.ini');

        return isset($templateConfig['perPageNum'][$key]) ? $templateConfig['perPageNum'][$key] : 16;
    }

    /**
     * 获取地区下级
     * @param int $topId
     * @return array|object[]|null
     */
    public function getRegionSub($topId = 0)
    {
        $region = $this->entityManager->getRepository(Region::class)->findBy(['regionTopId' => $topId], ['regionSort' => 'ASC']);
        return $region ? $region : null;
    }

    /**
     * 单页cms标签组
     * @param string $topName
     * @return string[]
     */
    public function shopSingleCmsTagOptions($topName = '')
    {
        $mobileCmsTagArray  = Common::getDefaultTemplateTag('articleSingleTag');
        $pcCmsTagArray      = Common::getDefaultTemplateTag('articleSingleTag', 'pcTemplate');

        $options = ['' => empty($topName) ? $this->translator->translate('===选择标签===') : $topName];
        if(!empty($pcCmsTagArray)) foreach ($pcCmsTagArray as $pcKey => $pcItem) {
            $options['pc-'.$pcKey] = $pcItem . '-' . $this->translator->translate('电脑端');
        }
        if(!empty($mobileCmsTagArray)) foreach ($mobileCmsTagArray as $mKey => $mItem) {
            $options['mobile-'.$mKey] = $mItem . '-' . $this->translator->translate('手机端');
        }

        return $options;
    }

    /**
     * 获取模板的信息
     * @param $key
     * @return mixed|null
     */
    public function shopTemplate($key)
    {
        $templateConfig = Factory::fromFile('module/Shop/view/'.Common::getShopDefaultTemplate().'/shop/template.ini');

        return isset($templateConfig[$key]) ? $templateConfig[$key] : null;
    }

    /**
     * 获取指定位置的区域内容调用
     * @param $location
     * @return array
     */
    public function shopPartial($location)
    {
        $partial = [];
        $shopDefaultTemplate    = Common::getShopDefaultTemplate();
        $shopDefaultTemplateCode= str_replace('/', '-', $shopDefaultTemplate);
        $config = Factory::fromFile('module/Shop/view/'.$shopDefaultTemplate.'/shop/templatePartial.ini');
        if(isset($config[$location])) foreach ($config[$location] as $key => $value) {
            $partial[$key]['partialFile'] = $value['partial'];
            if(isset($value['functionArg'])) {
                $partial[$key]['partialArg'] = $value['functionArg'];
                $partial[$key]['partialArg'][$value['partialBody']] = $this->getController()->shopPartialPlugin()->{$value['functionName']}($value['code'], $shopDefaultTemplateCode);
            } else $partial[$key]['partialArg'] = [$value['partialBody'] => $this->getController()->shopPartialPlugin()->{$value['functionName']}($value['code'], $shopDefaultTemplateCode)];
        }

        return $partial;
    }

    /**
     * 生成海报分享图片
     * @param $goodsInfo
     * @return string
     */
    public function shopGoodsShareQrCodeImage($goodsInfo)
    {
        //如果是商品的二维码，那么判断是否登录，登录则生成会员专用二维码
        $userId     = $this->checkUserLoginStatus() ? $this->sessionUser->offsetGet('user_id').'_' : '';

        $imagine    = new Imagine();
        $image      = $imagine->open(Config::COMMON_IMAGE_PATH . 'share_bg.png');
        $imageSize  = $image->getSize();
        $palette    = new RGB();
        $fontFile   = Config::COMMON_IMAGE_PATH . 'SourceHanSans-Normal.otf';
        $font       = $imagine->font($fontFile, 16, $palette->color("000000"));
        $thumbnailImage = $goodsInfo['goodsThumbnailImage'] ? Config::PUBLIC_PATH . $goodsInfo['goodsThumbnailImage'] : Config::COMMON_IMAGE_PATH . 'shop_goods.png';
        $goodsImage = $imagine->open($thumbnailImage)->resize(new Box(500, 500));
        $goodsSize  = $goodsImage->getSize();
        $image->paste($goodsImage, new Point(($imageSize->getWidth() - $goodsSize->getWidth())/2, 0));
        $goodsTitle = Common::cnRowSubstr($goodsInfo[0]->getGoodsName(), 2, 27);

        $yHeight = 505;
        $image->draw()->text($goodsTitle[1], $font, new Point(5, $yHeight));
        if(isset($goodsTitle[2]) && !empty($goodsTitle[2])) {
            $yHeight += 30;
            $image->draw()->text($goodsTitle[2], $font, new Point(5, $yHeight));
        }

        if($this->dbshopSession->offsetGet('currencyCode')) $currency = Common::configValue($this->dbshopSession->offsetGet('currencyCode'), 'currency');
        else $currency = Common::configValue('default', 'currency');

        $yHeight += 40;
        $image->draw()->text($this->translator->translate('价格'), $imagine->font($fontFile, 18, $palette->color('000000')), new Point(5, $yHeight));
        $image->draw()->text($currency['symbol'].' '.number_format($goodsInfo[0]->getGoodsPrice() * $currency['rate'], 2, '.', ','), $imagine->font($fontFile, 24, $palette->color('FF0000')), new Point(60, $yHeight-5));

        $qrCodeFile = Config::GOODS_QRCODE_IMAGE_PATH . $userId . $goodsInfo[0]->getGoodsId() . '.png';
        $shareGoodsUrl = $this->getController()->url()->fromRoute('shop-goods', ['id' => $goodsInfo[0]->getGoodsId()], ['force_canonical' => true]);
        if(!file_exists($qrCodeFile)) QRcode::png($shareGoodsUrl, $qrCodeFile, 0, 6, 1);
        $qrCodeImage= $imagine->open($qrCodeFile);
        $qrCodeSize = $qrCodeImage->getSize();
        $image->paste($qrCodeImage, new Point($imageSize->getWidth() - $qrCodeSize->getWidth() - 15, $yHeight));

        $image->draw()->text($this->translator->translate('温馨提示：长按图片识别二维码即可前往购买页面'), $imagine->font($fontFile, 15, $palette->color('000000')), new Point(10, $yHeight + $qrCodeSize->getHeight() + 40));
        $image->draw()->text($this->translator->translate('商城网站：') . $this->getController()->url()->fromRoute('shop', [], ['force_canonical' => true]), $imagine->font($fontFile, 15, $palette->color('000000')), new Point(10, $yHeight + $qrCodeSize->getHeight() + 70));

        $goodsQrCodeImage = Config::GOODS_QRCODE_IMAGE_PATH . $userId . $goodsInfo[0]->getGoodsId() . '_goods_'.$currency['code'].'.png';
        if(!file_exists($goodsQrCodeImage)) $image->save($goodsQrCodeImage);

        return str_replace(Config::PUBLIC_PATH, '', $goodsQrCodeImage).'?v='.time();
    }

    /**
     * 生成二维码
     * @param $text
     * @param $qrCodeFilePath
     * @param $fileName
     * @param bool $overwriteFile
     * @return string|string[]
     */
    public function shopCreateQrCodeFile($text, $qrCodeFilePath, $fileName, $overwriteFile = true)
    {
        $invitationQrCodeFile = $qrCodeFilePath . basename($fileName) . '.png';
        if(!file_exists($invitationQrCodeFile)) QRcode::png($text, $invitationQrCodeFile, 0, 6, 1);
        else {
            if(!$overwriteFile) return str_replace(Config::PUBLIC_PATH, '', $invitationQrCodeFile).'?v='.time();
            else QRcode::png($text, $invitationQrCodeFile, 0, 6, 1);
        }
        return str_replace(Config::PUBLIC_PATH, '', $invitationQrCodeFile).'?v='.time();
    }

}